﻿using HBFramework;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class Panel_GM : BasePanel
{
    public override int RemainTime => PanelRemainTime.Never;

    public override int Layer => PanelLayer.GM;

    public override string Path => "ui/panel_gm";

    private TMP_InputField if_command;
    private Button btn_send;
    private GameObject item_tab;
    private GameObject item_btn;

    private GMCommands commands;
    private List<GMMethod> methods;
    private Dictionary<string, List<GMMethod>> methodDict;
    private List<GMTabItem> tabs;
    private Dictionary<string, List<GMBtnItem>> btnDict;
    private GameObjectPool itemBtnPool;

    public override void OnInit(GameObject ui)
    {
        if_command = ui.transform.Find("root_top/if_command").GetComponent<TMP_InputField>();
        btn_send = ui.transform.Find("root_top/btn_send").GetComponent<Button>();
        item_tab = ui.transform.Find("root_bottom/root_tab/item_tab").gameObject;
        item_btn = ui.transform.Find("root_bottom/Scroll View/Viewprot/Content/item_btn").gameObject;

        itemBtnPool = new GameObjectPool(item_btn);
        btn_send.onClick.AddListener(OnSendBtnClick);

        commands = new GMCommands();
        var allMethods = typeof(GMCommands).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        methodDict = new Dictionary<string, List<GMMethod>>();
        methods = new List<GMMethod>();
        foreach (var item in allMethods)
        {
            var atbs = item.GetCustomAttributes(typeof(GMAttribute), false);
            if (atbs.Length <= 0)
            {
                continue;
            }
            var atb = atbs[0] as GMAttribute;
            if (!methodDict.ContainsKey(atb.group))
            {
                methodDict.Add(atb.group, new List<GMMethod>());
            }
            var gmm = new GMMethod(atb, item);
            methodDict[atb.group].Add(gmm);
            methods.Add(gmm);
        }
        CreateTabs();
        SelectTab(methodDict.Keys.First());
    }

    public override void OnRelease()
    {
        btn_send.onClick.RemoveListener(OnSendBtnClick);
    }

    private void OnSendBtnClick()
    {
        if (string.IsNullOrEmpty(if_command.text))
        {
            return;
        }
        var args = if_command.text.Split(' ').ToList();
        var methodName = args[0];
        args.RemoveAt(0);
        foreach (var method in methods)
        {
            if (method.attribute.name == methodName)
            {
                method.method.Invoke(commands, new object[] { args });
                break;
            }
        }
    }

    private void CreateTabs()
    {
        tabs = new List<GMTabItem>();
        foreach (var item in methodDict.Keys)
        {
            GameObject go = GameObject.Instantiate(item_tab, item_tab.transform.parent, false);
            var tab = new GMTabItem(go, item, SelectTab);
            tabs.Add(tab);
        }
        item_tab.SetActive(false);
        btnDict = new Dictionary<string, List<GMBtnItem>>();
        foreach (var item in methodDict)
        {
            btnDict.Add(item.Key, new List<GMBtnItem>());
            for (int i = 0; i < item.Value.Count; i++)
            {
                var method = item.Value[i];
                GMBtnItem btn = new GMBtnItem(method.attribute, OnItemBtnClick);
                btnDict[item.Key].Add(btn);
            }
        }
    }

    private void SelectTab(string group)
    {
        itemBtnPool.RecycleAll();
        var btns = btnDict[group];
        foreach (var item in btns)
        {
            var btnGo = itemBtnPool.RentObject();
            btnGo.transform.SetParent(item_btn.transform.parent, false);
            btnGo.gameObject.SetActive(true);
            item.BindItem(btnGo);
        }
        item_btn.SetActive(false);
    }

    private void OnItemBtnClick(string template)
    {
        if_command.text = template;
    }
}
